using System;
using System.Collections.Generic;
using System.Text;
using Boo.Lang.Interpreter;
using System.ComponentModel;
using Microsoft.BizTalk.Component.Interop;
using Boo.Lang.Compiler;
using System.Text.RegularExpressions;


namespace TCPSoftware.BizTalk.PipelineComponents.MockPipelineComponent.Evaluator.Boo 
{ 
    public class BooScriptDisassemblerManager : Microsoft.BizTalk.Component.Interop.IDisassemblerComponent, IProbeMessage
    {
        private Microsoft.BizTalk.Component.Interop.IDisassemblerComponent innerComponent;

        private const String IMPORT_REGEX = "^import (.*) from \"(.*\\\\(.*)\\.dll)\"";

        public BooScriptDisassemblerManager(Dictionary<String, Object> bag)
        {
            System.IO.StreamReader sr = null;
            try
            {
                InteractiveInterpreter interpreter = new InteractiveInterpreter();

                interpreter.References.Add(
                    System.Reflection.Assembly.LoadWithPartialName("Microsoft.BizTalk.Pipeline"));
                //  pb.Read(propName, out val, 0);
                object text;
                text = bag.ContainsKey("scriptFile") ? bag["scriptFile"] : null;
                sr = new System.IO.StreamReader(System.Environment.ExpandEnvironmentVariables(Convert.ToString(text)));
                StringBuilder sb = new StringBuilder();
                while (!sr.EndOfStream)
                {
                    string row = sr.ReadLine();

                    if (Regex.Match(row, IMPORT_REGEX).Success)
                    {
                        GroupCollection g = Regex.Match(row, IMPORT_REGEX).Groups;
                        interpreter.References.Add(System.Reflection.Assembly.LoadFile(g[2].Value.Replace("\\\\", "\\")));
                        // replace with truncated version.
                        row = String.Format("import {0} from \"{1}\"", g[1], g[3]);
                    }

                    sb.AppendLine(row);
                }

                string scriptcontent = sb.ToString();

                interpreter.SetValue("bag", bag);


                CompilerContext ctx = interpreter.Eval(scriptcontent);
                if (!String.IsNullOrEmpty(ctx.Errors.ToString(true))) throw new CompilerError(ctx.Errors.ToString(true));
                text = bag.ContainsKey("outputVariable") ? bag["outputVariable"] : null;
                innerComponent = (Microsoft.BizTalk.Component.Interop.IDisassemblerComponent)interpreter.GetValue(Convert.ToString(text));
            }
            finally
            {
                if (sr != null) { sr.Close(); }
            }
            
        }
    
    #region IDisposable Members

    //public void Dispose()
    //{
    //    throw new Exception("The method or operation is not implemented.");
    //}

    #endregion

    #region IComponent Members

    //public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(IPipelineContext pContext, Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
    //{
    //    return innerComponent.Execute(pContext, pInMsg);
    //}

    #endregion

#region IDisassemblerComponent Members

public void  Disassemble(IPipelineContext pContext, Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
{
    innerComponent.Disassemble(pContext, pInMsg);
}

public Microsoft.BizTalk.Message.Interop.IBaseMessage  GetNext(IPipelineContext pContext)
{
    return innerComponent.GetNext(pContext);
}

#endregion

#region IProbeMessage Members

public bool Probe(IPipelineContext pContext, Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
{
    if (innerComponent is IProbeMessage)
        return ((IProbeMessage)innerComponent).Probe(pContext, pInMsg);
    else return true;
}

#endregion
} 
}



